\documentclass[UTF8]{book}
\usepackage{titletoc}
\usepackage[noindent]{ctex}
\usepackage{indentfirst}
\usepackage{listings}
\usepackage[colorlinks,linkcolor=red]{hyperref}
\hypersetup{colorlinks=true,linkcolor=black}
\usepackage{geometry}

\usepackage{amsmath}

\usepackage{graphicx}
\graphicspath{{image/}}

\usepackage{caption}

\usepackage{tikz}
\usetikzlibrary{shapes,arrows}
\usetikzlibrary{shapes.geometric}
\usepackage{array}

\geometry{left=2.5cm,right=2.5cm,top=2.5cm,bottom=2.5cm}

\lstset{
	numbers=left, 
	numberstyle= \tiny, 
	keywordstyle= \color{ blue!70},
	commentstyle= \color{red!50!green!50!blue!50}, 
	frame=shadowbox, % 阴影效果
	rulesepcolor= \color{ red!20!green!20!blue!20} ,
	escapeinside=``, % 英文分号中可写入中文
	xleftmargin=2em,xrightmargin=2em, aboveskip=1em,
	framexleftmargin=2em
} 
\begin{document}

\tableofcontents
  
\chapter{C++ 学习笔记}
    \section{常识}
        extension file name不一定是.h或.cpp也可能是.hpp或其他或甚至无延伸名。

        c++中的二元操作符都是作用在操作符右侧的变量上。

        cout是一个global对象，它的type为ostream。
    \section{基础学习}
    	\subsection{callconvention}
    	
    	\subsection{DLL和EXE}
    		参考：\url{http://blog.csdn.net/u013037007/article/details/47158639}
    		\subsubsection{注意点}
    		\paragraph{.a和.lib的区别}
    		.a结尾是linux静态库文件。
    		
    		.lib结尾应该是windows静态库文件。
    		
    		.a is an archive of code: compiled but not linked. You would link statically with it during your program's final link step.
    		
    		.lib can be either the same as .a, or a magical so-called "import library": a thin placeholder which causes you to require a .dll at runtime.
    		\paragraph{.a在codeblocks下的使用和linux下的使用和VC中使用}
    		At first,create a sll project in codeblocks.
    		
    		主要是提前在$setting->compiler->linker setting$中将静态库路径放进来。
    		
    		在linux系统中可以直接在makefile中来设置。
\begin{lstlisting}[language=C++]
all:  
gcc -o main main.c -lcompute -L.  

lib:  
gcc -o add.a -c add.c -static  
gcc -o mul.a -c mul.c -static  
ar -rc libcompute.a add.a mul.a  

clean:  
rm -f *.o *.a main  
\end{lstlisting}
    		Then to get sll by making lib.
    		
    		Vc中使用类似codeblocks，需要设置linker,另一种方式是使用命令progma comment(lib,"")来添加。
    		\paragraph{linux下静态库、共享库和动态库}
    		
    		\subsubsection{DLL与SLL的区别}
    		静态链接库与动态链接库都是共享代码的方式，如果采用静态链接库，则无论你愿不愿意，lib中的指令都被直接包含在最终生成的EXE文件中了。
    		
    		但是若使用DLL，该DLL不必被包含在最终EXE文件中，EXE文件执行时可以“动态”地引用和卸载这个与EXE独立的DLL文件。
    		
    		静态链接库和动态链接库的另外一个区别在于静态链接库中不能再包含其他的动态链接库或者静态库，而在动态链接库中还可以再包含其他的动态或静态链接库。
    		\subsubsection{加深DLL的理解}
    		\paragraph{LL 的编制与具体的编程语言及编译器无关}
    		
    		只要遵循约定的DLL接口规范和调用方式，用各种语言编写的DLL都可以相互调用。
    		
    		譬如Windows提供的系统DLL（其中包括了Windows的API），在任何开发环境中都能被调用，不在乎其是Visual Basic、Visual C++还是Delphi。
    		
    		\paragraph{动态链接库随处可见}
    		我们在Windows目录下的system32文件夹中会看到kernel32.dll、user32.dll和gdi32.dll，windows的大多数API都包含在这些DLL中。
    		
    		kernel32.dll中的函数主要处理内存管理和进程调度；user32.dll中的函数主要控制用户界面； gdi32.dll中的函数则负责图形方面的操作。
    		
    		一般的程序员都用过类似MessageBox的函数，其实它就包含在user32.dll这个动态链接库中。
    		
    		由此可见DLL对我们来说其实并不陌生。
    		\paragraph{VC动态链接库的分类}
    		Visual C++支持三种DLL，它们分别是Non-MFC DLL（非MFC动态库）、MFC Regular DLL（MFC规则DLL）、MFC Extension DLL（MFC扩展DLL）。
    		
    		非MFC动态库不采用MFC类库结构，其导出函数为标准的C接口，能被非MFC或MFC编写的应用程序所调用。
    		
    		MFC规则DLL 包含一个继承自CWinApp的类，但其无消息循环；MFC扩展DLL采用MFC的动态链接版本创建，它只能被用MFC类库所编写的应用程序所调用。
    		
    		
        \subsection{Header的布局}
            结合实例：
\begin{lstlisting}[language=C++]
//guard
#ifndef __XXX__
#define __XXX__

#include <cmath>

 //forward declarations
class ostream;
class complex;
complex & __doapl (complex* ths,const complex& r);

//class declarations
class complex      //class head
{
//class body,简短的函数可以在这里直接定义即inline。
//function。最后是否为inline由编译器决定，
//若在body外定义inline function //可以通过添加关键字inline
};

//class definition
complex::function ...

#endif
\end{lstlisting}
        \subsection{UML符号}
        +:public，-:private，$\#$:protect,下划线静态。
        \subsection{function template}
\begin{lstlisting}[language = C++]
template <class T>
inline
const T& min(const T& a,const T& b)
{
    return b<a ? b:a;//<会使用重载后的小于函数。
}

//使用
stone r1(2,3),r2(3,3),r3;
r3 = min(r1,r2);
//编译器会对functoin template进行形参推导(argument deduction)
//即根据参数的类型来选定模板函数中T的值。
\end{lstlisting}
        \subsection{class template介绍}
\begin{lstlisting}[language = C++]
template<typename T>//告知编译器数据类型未定
class complex
{
public://access level
    //constructor，ctor构造函数
    complex(T r=0,T i=0)//默认实参default argument
        :re(r),im(i)//初值列initialization list构造函数独有比较大气
    {}
    complex& operator += (const complex&);
    T real () const {return re;}
    T imag () const {return im;}
private:
    T re,im;

    friend complex& __doapl(complex*,const complex&);
};

//使用：
complex<double> c1(2.5,1.5);
complex<int> c2(2,6);
...
}
\end{lstlisting}
        \subsection{composition}
        特例：

            Adapter；弱功能结构包含强功能结构。

        符号：实心菱形。

        生命周期：

            Container和Component同生命周期。

        构造由内而外。
\begin{lstlisting}[language = C++]
Container::Container():Component(){};//Component由编译器来处理
\end{lstlisting}
        析构由外而内。
\begin{lstlisting}[language = C++]
Container::~Container(){~Component()};
\end{lstlisting}


        \subsection{Delegation}
        composition by reference(包括指针和引用)。

        符号：空白菱形。

        生命周期：

            主体和被委托对象的生命周期不一致，被委托对象只有在被需要时才被创建。

        如：
\begin{lstlisting}[language = C++]
//将Handle和Body分开来。
//file String.hpp
class StringRep;
class String
{
    ...
private:
    StringRep * rep;//point to implementation
                    //另一个好处是可以实现body共享copy时的共享
};
//file StringRep.hpp//编译防火墙
class StringRep
{
    friend class String;
    ...
    int count;//共享copy的个数
            //若一个copy对象发生copy on write时，
            //可以单独再这个对象分配body 并write修改内容
}
\end{lstlisting}
        \subsection{inheritance和虚函数}
            有private、protect、public三种继承。

            继承最有价值之处在于：和虚函数的搭配使用with virtual fucntions。

            注意：base class 的dtor必须是virtual，否则会出现undefined behavior。

        符号：空心三角形。

        构造由内而外。

        析构由外而内。
        \subsection{DIC组合}
        最常用的组合：Delegation和Inheritance。

        1、观察者模式：处理存储数据和表现数据之间的关系。

        2、Composite。

        3、Prototype。
        \subsubsection{virtual functions}
        分两类：1、pure virtual，2、impure virtual。

        impure virtual已有默认定义。

        实例：
\begin{lstlisting}[language = C++]
class Shape
{
    public:
        virtual void draw()const=0;//纯虚函数后添加了=0
        virtual void error(const std::string& msg){};//impure virtual
    ...
}
\end{lstlisting}
        \subsection{构造函数}
            \subsubsection{构造函数可以overloading重载}
            如：
\begin{lstlisting}[language = C++]
complex(double r=0,doublei=0)
    :re(r),im(i)
{ }
complex():re(0),im(0){ }
\end{lstlisting}
            \subsubsection{构造函数放在private中}
            如singleton单体
\begin{lstlisting}[language = C++]
class A
{
    public:
        static A& getInstance();//静态
        setup(){...}
    private:
        A();
        A(const A& rhs);
        ...
};
A& A::getInstance()
{
    static A a;//这个设计只给静态创建一份
    return a;
}
}
\end{lstlisting}

        \subsection{对<<的重载}
\begin{lstlisting}[language = C++]
ostream&
operator << (ostream& os,const type& )
{
    return os << '(';
    ...
}
\end{lstlisting}
        \subsection{常量成员函数}
            如：不会改变数据内容
\begin{lstlisting}[language = C++]
class complex
{
...
    double real()const {return re;}
...
}
\end{lstlisting}
            常会出现的逻辑矛盾
\begin{lstlisting}[language = C++]
class complex
{
    ...
    double real(){return re;}//设计者定义re可变
    ...
}
//使用者
{
    const complex c1(2,1);//使用者定义使用的复数不可变
    cout << c1.real();
}
\end{lstlisting}
        \subsection{参数传递和返回值传递}
            \subsubsection{pass(return) by value vs.pass(return) by reference引用(to const)}
            pass（return） by value:它是整包传递并压入stack中。所以尽量不要使用。

            解决：

                1、过去使用指针，只传递指针。

                2、在c++中使用引用（pass（return） by refernce）。

            指针和引用的区别：

            本质上是一样的都是指针，引用是c++对指针做了一个外包装（对地址封装），使

            用更方便。

            引用的使用应该避开local object。

            pass（return） by reference（to const）:引用和不可改。
            \subsubsection{创建临时对象temp object}
                使用typename()来创建临时对象，没有变量名，它的生命在下一行结束。
        \subsection{friend友元}
            在c++中，朋友之间可以直接取数据，打破封装自由取得friend的private成员。
            \subsubsection{相同class的各个objects互为friends友元}
            如：
\begin{lstlisting}[language = C++]
class complex
{
    public:
        complex (double r=0,double i=0)
        :re(r),im(i)
        {
        }
        int func(const complex& param)
        { return param.re + param.im;}
    private:
        double re,im;
};

{
    complex c1(2,1);
    complex c2;

    c2.func(c1);
}
\end{lstlisting}
        \subsection{class中的static}
            静态函数中不能使用this指针，即静态函数中只能处理静态变量。

            静态变量必须在class声明后定义。
            
            如：
\begin{lstlisting}[language = C++]
class Account
{
public:
    static double m_rate;
    static void set_rate(const double &x){m_rate = x;}
};
double Account::m_rate = 8.0;
\end{lstlisting}
            调用static函数的方法：

            1、通过object调用。

            2、通过class name调用。
        \subsection{template template parameter}
\begin{lstlisting}[language = C++]
template<typename T,
    template<typename T>
        class Container   //class和typename在<>中意义相同
        >
class XCls
{
    private:
        Container<T> c;
    public:
        ...
};
template<typename T>
using Lst = list<T,allocator<T>>;

XCls<string,list> mylst1;//错误，因为list容器有第二模板参数
XCls<string,Lst> mylst2;
\end{lstlisting}
\begin{lstlisting}[language = C++]
//以下为不是template template parameter的典型
template <class T,class Sequence = deque<T>>
class stack
{
    ...
}
stack<int> s1;
stack<int,list<int>> s2;
\end{lstlisting}
        \subsection{variadic数量不定template}
\begin{lstlisting}[language = C++]
void print()
{
}
template<typename T,typename... Types>
void print(const T&firstArg,const Types&... args)
{
    cout<<firstArg<<endl;
    print(args...);
}
//bit模板的使用:bitset<16>(377);
\end{lstlisting}
        \subsection{auto}
\begin{lstlisting}[language = C++]
//版本一
list<string> c;
...
list<string>::iterator ite;
ite = find(c.begin(),c.end(),target);
//版本二
list<string> c;
...
auto ite = find(c.begin(),c.end(),target);
//错误版本
list<string> c;
...
auto ite;
ite = find(c.begin(),c.end(),target);
\end{lstlisting}
        \subsection{ranged-base for pass by value or reference}
\begin{lstlisting}[language = C++]
vetor<double> vec;
...
for(auto elem:vec)
{
    cout<<elem<<endl;//pass by value
}

for(auto& elem:vec)
{
    elem *=3;//pass by reference
}
\end{lstlisting}
        \subsection{reference}
        引用：reference to 对象，指针：pointer to 对象。

        常用于参数传递，而不常用于声明变量。
\begin{lstlisting}[language = C++]
int x=0;
int *p = &x;
int & r=x;//r代表x。现在r,x都是0，r只是一个假象
int x2=5;

r=x2;//r 不能重新代表其他物体。现在r,x都是5
int & r2=r;

//注意：same signature
double imag(const double & im){ ...}
double imag(const double im){ ...}

//注意：different signature
double imag(const double & im)const{...}
double imag(const double & im){...}
\end{lstlisting}
    \section{内存管理}
        \subsection{基本构件}
            \subsubsection{new and delete}
                new主要做了两个事：1、分配内存memory，2、调用构造函数ctor。

                delete主要做了：1、析构函数dtor，2、释放内存memory。
        \subsection{动态分配内存块}
            \subsubsection{new and delete}
            gnu编译器下memory block的字节数为16的倍数，memory block在release mode下的组成为：有用块+cookie（8个字节）。

            cookie:something about bookeeping，主要是记录内存块的长度。

            小饼干是malloc和free之间的约定。

            在调试模式下的memory block占用的内存会大的多，每个内存块都需要大约50 个字节的附加信息。
            \subsubsection{new array}
            当array中元素为指针时，array new 和array []delete需要搭配使用，否则会导致memory leak。
            
            当array中元素不为指针时，array new和array []delete不搭配使用可能会造成内存泄漏，视array中object的析构函数是否有意义而定。

            array new会多次调用默认构造函数，即使用array new时必须要有默认构造函数。
            
            形如：
\begin{lstlisting}[language = C++]
A* buf=new A[size];
delete []buf;
\end{lstlisting}
            改进：
\begin{lstlisting}[language = C++]
A* buf = new A[size]//分配空间并调用默认构造函数
A* tmp =buf;
for(int i=0;i<size;++i)
    new(tmp++)A(i);//调用构造函数。
delete []buf;
\end{lstlisting}
            \subsubsection{placement new}
            没有placement delete，placement new 允许将object建立与allocated memory 中，placement new 根本没分配memory。
            形如：
\begin{lstlisting}[language = C++]
#include <new>
char * buf=new char[sizeof(Complex)*3];
Complex * pc=new(buf)Complex(1,2);
...
delete [] buf;
\end{lstlisting}
        \subsection{allocator的选择}
        gnuc++体制内自带标准的allocator对内存没有进行管理，建议使用外带$\_\_pool\_alloc$。
        \subsection{free-list}
        注意内存管理的阶段：1、自由内存，2、被free-list管理的内存(需要embeded pointers)，3、被客户管理的内存(使用客户容器对象来取代embeded pointers)。
        \subsection{new handler处理内存分配不足的异常}

        \subsection{default and delete}
            拷贝构造、拷贝复制、析构会有默认函数。
\begin{lstlisting}[language = C++]
//如：
class xxx{
    void function()=default;
}
\end{lstlisting}
        \subsection{Ctor和Dtor直接调用}
            Ctor不能被直接调用，Dtor可以被直接调用。
    \section{算法}
        \subsection{动态规划和递归}
        DP：dynamic planning。

        相同点：能分解成若干子问题。

        不同点：DP储存子问题的结果。

        1、bottom-up

        2、top-down
        
        fibonacci number
\begin{lstlisting}[language = C++]
int array[n] = {0};
array[1] = 1;
for(int i=2;i<n;i++)
    array[i]=array[i-1]+array[i-2];//空间换时间。
\end{lstlisting}

    \section{Object Based面对的是单一class的设计}
        \subsection{class without pointer members}
            多半不用写析构函数。
        \subsection{class with pointer members}
            带指针需要写析构函数。
            
        class with pointer members必须有copy ctor和copy op=

        在拷贝复制函数中应该注意“self assignment”

\begin{lstlisting}[language = C++]
if(this == &object)
    return *this;
\end{lstlisting}
    \section{高阶}
        \subsection{conversion function}
        1、转换出去（只要合理，转换函数不唯一）
\begin{lstlisting}[language = C++]
class Fraction
{
    public:
        Fraction(int num,int den=1)
        :m_numerator(num),m_denominator(den)
        { }
        operator double()const
        {//转换函数，以返回类型为函数名
            return (double)(m_numerator/m_denominator);
        }
        Fraction operator+(const Fraction& f)
        {
        }
    private:
        int m_numerator;
        int m_denominator;
}
//使用
Fraction f(3,5);
double d=4+f;//调用operator double 将f转换为double类型

Fraction d2 = f+4//error它产生了二义性，第一条：0.6+4=4.6
//第二条：3/5+4=23/4
\end{lstlisting}

        \subsection{non-explicit-one-argument ctor}
        2、转进来。

        可以将别的东西4转为想要的东西4/1。
\begin{lstlisting}[language = C++]
class Fraction
{
public:
    Fraction(int num,int den=1)//one-argument,只要一个实参,另个形参有默认值
    :m_numerator(num),m_denominator(den){ }
    Fraction operator+(const Fraction& f)
    {
    }
private:
    int m_numerator;
    int m_denominator;
};

Fraction f(3,5);
Fraction d2=f+4;//调用 non-explicit ctor 将4转为Fraction(4,1)
                //然后调用operator+

\end{lstlisting}
        \subsection{explicit-one-argument ctor}
        明确的，不会自动将4转化为分数类型。
\begin{lstlisting}[language = C++]
class Fraction
{
public:
    explict Fraction(int num,int den=1)//one-argument,只要一个实参,另个形参有默认值
    :m_numerator(num),m_denominator(den){ }
    Fraction operator+(const Fraction& f)
    {
    }
private:
    int m_numerator;
    int m_denominator;
};

Fraction f(3,5);
Fraction d2=f+4;//error因为4不会被转换为分数，所以在调用operator+
                //会出现实参形参类型不一致的错误。
\end{lstlisting}
        \subsection{pointer-like classes智能指针}
        比指针多一些功能，如对++和--进行重载。
        
        实例：迭代器。

        \subsection{function-like classes 仿函数或函数对象}
        funciton( )为function call operation。

        标准库中有很多仿函数。

        如：
\begin{lstlisting}[language = C++]
template <class T>
struct identity：unary_function //identity意为视为同一
{
    const T&
    operator()(const T& x)const{return x;}
};
template <class Pair>
struct select1st: unary_function
{
    const typename Pair::first_type&
    operator()(const Pair&x)const
    {return x.first}
};
\end{lstlisting}
    \section{GOF设计模式}
        模式：可复用面向对象的软件。

        底层思维：向下，如何把握底层从微观理解对象构造。（语言构造、编译转换、内存模型、运行时机制）

        封装，隐藏内部实现。

        继承，复用现有代码。

        多态，改写对象代码，各负其责。

        抽象思维：向上，如何将我们的自卫世界抽象为程序代码（面向对象、组件封装、设计模式、架构模式）

        依赖关系：编译时依赖。

        如何解决复杂性？

        1、分解，各种类型分而治之不易复用。2、抽象，忽视非本质细节并使用通用的方法统一处理。
        \subsection{面向对象设计原则}
            面向对象的最大优势在于：抵御变化，提高复用。

            扩展=继承+override多态。

            变化：各类指针、继承后override虚函数（扩展）、引用（不常用）。

            稳定：函数、变量。
            \subsubsection{对象是什么？}
            1、语言层面：封装了代码和数据。

            2、规格层面：一系列可被使用的公共接口。

            3、概念层面：拥有责任的抽象。
            \subsubsection{重构获得模式}
            1.什么是好的面向对象设计？

                能应对变化，提高复用。
            2.软件设计的特征：需求的频繁变化。

              设计模式的要点是寻找变化点，然后在变化点处应用设计模式，从而来更好地应对需求的变化。（什么时候、什么地点应用设计模式？）

            3.没有一步到位的设计模式，Refactoring to Patterns。（重构完善）

            《重构与模式》和《重构-改善既有代码的设计》

            \subsubsection{DIP依赖倒置原则:稳定隔离变化}
            概述:

            高层模块（稳定）不应该依赖于底层模块（变化），二者度应该依赖于抽象（稳定）。

            抽象（稳定）不应该依赖于实现细节（细节），实现细节应该依赖于抽象（稳定）。

            \begin{tikzpicture} [
               auto,
               block/.style    = { rectangle, draw=blue, thick,
                        fill=blue!20, text width=10em, text centered,
                        rounded corners, minimum height=2em },
               block_noborder/.style ={rectangle, draw=none, thick, fill=none,
                      text width=10em, text centered, minimum height=1em},
               line/.style     = { draw, thick, ->, shorten >=2pt }
            ]
            \matrix [column sep=10mm, row sep=3mm] {
                \node [block] (b1) {Mainform:稳定、高层模块};
                & \node [block] (b2) {Rect:变化、底层模块};
                \\ \node [block_noborder] (b) {Bad!};
                &\node [block] (b5) {Line:变化、底层模块};&
                \\\\ 			
                \node [block] (b3) {Shape:稳定、抽象};
                &\node [block] (b4) {Rect:变化、底层模块};\\
                \node [block_noborder] (b) {Bad!};
                &\node [block] (b6) {Line:变化、底层模块};
                \\\\
                \node [block] (b8) {Shape:稳定、抽象};
                &\node [block] (b9) {Rect:变化、底层模块}; \\
                \node [block_noborder] (b) {依赖倒置原则};
                &\node [block] (b0) {Line:变化、底层模块}; \\

                &\node [block] (b7) {Mainform:稳定、高层模块};\\
            };

            \begin{scope} [every path/.style={line}]
	           \path(b1) -- (b2);
	           \path(b1) --++ (2,0) node [near start]{} |-(b5);
	           \path(b3) -- (b4);
	           \path(b3) --++ (2,0) node [near start]{} |-(b6);
	           \path(b7) --++ (-2,0)node [near start]{} |- (b8);
	           \path(b9) -- (b8);
	           \path(b0) --++ (-2,0)node [near start]{} |-(b8);
            \end{scope}
            \node (leyend) at (7.5,0){
            \begin{tabular}{>{\sffamily}l@{: }l}
            \multicolumn{1}{c}{\textbf{Note:}} \\
            $\rightarrow$ & 依赖于     \\
            Bad! & 不好的依赖关系\\
            \end{tabular}
            };
            \end{tikzpicture}
            \subsubsection{开放封闭原则OCP}
            概述:

            对扩展开放，对更改封闭。

            类模块应该是可扩展的，但是不可修改。

            （对稳定部分封闭，对变化部分开放。）
            \subsubsection{单一职责原则SRP}
            概述:

            一个类应该仅有一个引起它变化的原因。

            变化的方向隐含着类的责任。

            \subsubsection{替换原则LSP（继承关系）}
            概述：

            子类必须能够替换它们的积累（IS-A）。

            继承表达类型抽象。

            \subsubsection{接口隔离原则ISP}
            概述:

            不应该强迫客户程序依赖它们不用的方法。

            接口应该小而完备。

            \subsubsection{优先使用对象组合，而不是继承}
            概述：

            类继承通常为“白箱复用”，对象组合通常为“黑箱复用”

            继承在某种程度上破坏了封装性，子类父类耦合度高。

            而对象组合则只要求被组合的对象具有良好定义的接口，耦合度低。

            \subsubsection{封装变化点}
            概述：

            使用封装来创建对象之间的分解层，让设计者可以在分层在一侧进行修改，而不会对另一侧产生不良的影响，从而实现层次间的松耦合。

            \subsubsection{针对接口编程，而不是针对实现编程}
            概述：

            不将变量类型声明为某个特定的具体类，而是声明为某个接口。

            客户程序无需获知对象的具体类型，只需要知道对象所具有的接口。

            减少系统中各部分的依赖关系，从而实现“高内聚、松耦合”的类型设计方案。

            解释：

            面向接口设计意味着“接口标准化”，
            \subsubsection{设计经验}
            1.设计习语Design Idioms

            描述与特定编程语言相关的底层模式，技巧，惯用法。

            2.设计模式Design Patterns

            描述“类与相互通信的对象之间的组织关系，包括它们的角色、职责、协作方式等方面。解决变化中的复用性问题。

            3.架构模式Architectural Patterns

            描述系统中与基本结构组织关系密切的高层模式，包括子系统划分，职责，以及如何组织它们之间关系的规则。
        \subsection{重构关键技法}
            1.静态$\rightarrow$ 动态

            2.早绑定$\rightarrow$ 晚绑定

            3.继承$\rightarrow$组合

            4.编译时依赖$\rightarrow$运行时依赖

            5.紧耦合$\rightarrow$松耦合

        \subsection{组件协作}
            框架与应用，组件协作通过晚期绑定来实现框架与应用之间的松耦合。
            \subsubsection{Template Method}
            动机：有稳定的整体操作结果，但各个子步骤有很多改变的需求，或者由于固有原因（比如框架与应用之间的关系）而无法和任务的整体结构同时实现。

            如何在确定稳定操作结构的前提下，来灵活应对各个子步骤的变化或者晚期实现需求？

            模式定义：定义一个操作中的算法的骨架（实例中的run）（稳定），而将一些步骤延迟（变化）到子类中。
            
            Template Method 使得子类可以不改变（复用）一个算法的结构即可重定义（override重写）该算法的某些特定步骤。《设计模式》GoF

            选择该模式的前提：run（骨架）必须相对稳定（一年一变化比一月一变化要稳定）。

            极端：若一个程序中所有组件都不稳定都在变化，则不建议使用设计模式。
            
            使用设计模式的前提是至少有一个稳定点。
            
            若一个程序所有组件都稳定，则设计模式便毫无意义。

            设计模式的灵魂：在稳定与变化之间找隔离点，然后来分离它们从而来管理变化。
            
            将变化关到笼子里。

            其中的虚函数推荐用protected。

           \includegraphics[width=7cm, height=5cm]{template}
           
            \subsubsection{Strategy}
            动机：在软件构建过程中，某些对象使用的算法可能多种多样，经常改变，如果将这些算法都编码到对象中，将会使对象变得异常复杂；而且有时候支持不使用的算法也是一个性能负担（if else会增加代码段的开销）。

            如何在运行时根据需要透明地更改对象的算法？将算法与对象本身解耦，从而避免上述问题？

            模式定义：

            定义一系列算法，把他们一个个封装起来，并且使它们可互相替换（变化）。
            
            该模式使得算法可独立于使用它的客户程序（稳定）而变化（扩展，子类化）。
            
            《设计模式》GoF

            当有出现if else和switch可以考虑使用策略模式，if else和switch是传统的分而治之。决定稳定不变（如一星期7天）则可以使用if else。

            灵魂：用使用扩展的方式来应对以后业务的变化。
            
            \includegraphics[width=14cm, height=6cm]{strategy}
            
            \subsubsection{Observer/Event/观察窗口/向篮子里放鸡蛋}
            主要还是解决框架与应用的协作问题。

            动机：在软件构建过程中，我们需要为默写对象建立一种“通知依赖关系”--一个对象（目标对象）的状态发生改变，所有的依赖对象（观察者对象）都将得到通知。
            
            如果这样的依赖关系过于紧密，将使软件不能很好地抵御变化。

            使用面向对象技术，可以这种依赖关系弱化，并形成一种稳定的依赖关系。
            
            从而实现软件体系结构的松耦合。

            多继承：一个基类多个接口。

            模式定义：

            定义对象间的一种一对多（变化）的依赖关系，以便当一个对象（Subject）的状态发生改变时，所有依赖于它的对象都得到通知并自动更新。
            
            《设计模式》

            java中的listen和中的事件都是使用了观察者模式。

            \includegraphics[width=14cm, height=8cm]{observer}
        \subsection{单一职责}
            \subsubsection{Decorator}
                设计模式的妙处：编译时让它们一样，让它们运行时不一样。
                
                编译时让它复用，它的变化、需求变化都放到运行时使用多态的方式让它支持变化。

                继承：编译时复用（提供接口），组合：运行时复用。

                原则：如果某一个类，它有多个子类都有同样的字段，应该把这个往上提。

                动机：在某些情况下我们可能会“过度地使用继承来扩展对象的功能”。
                
                由于继承为类型引入的静态特质，使得这种扩展方式缺乏灵活性；并且随着子类的增多（扩展功能的增多），各种子类的组合（扩展功能的组合）会导致更多子类的膨胀。

                如何使“对象功能的扩展”能够根据需要来动态地实现？
                
                同时避免“扩展功能的增多”带来的子类膨胀问题？
                
                从而使得任何“功能扩展变化”所导致的影响降为最低？

				\includegraphics[width=9cm, height=7cm]{decorator}
            \subsubsection{Bridge}
                动机：由于某些类型的固有的实现逻辑，使得它们具有两个变化的维度，乃至多个维度的变化。

                如何应对这种“多维度的变化”？
                
                如何利用面向对象技术来使得类型可以轻松地沿着两个乃至多个方向变化，而不引入额外的复杂度？

                模式定义：将抽象部分（业务功能）与实现部分（平台实现）分离，使它们都可以独立地变化。

                \includegraphics[width=14cm, height=6cm]{bridge}
                
        \subsection{从范围划分}
            \subsubsection{类模式处理类与子类的静态关系（偏继承）}

            \subsubsection{对象模式处理对象间的动态关系（偏组合）}

        \subsection{C++语言知识点}
            Algorithms + Data Structures = Programs。
            \subsubsection{1、类中使用虚的析构函}
\begin{lstlisting}[language=C++]
class Example{
public:
    virtual ~Example(){}
};
\end{lstlisting}
            \subsubsection{2、指针和多态}

    \section{STL学习笔记}
        \subsection{六大部件}
            1.容器(Containers):解决了存储结构的问题。

            2.分配器(Allocators):支持容器分配存储单元的数目。

            3.算法(Algorithms):功能模板函数操作。

            4.迭代器(Iterators):泛化指针，为了访问和存储内存。

            5.适配器(Adapters):转换器（容器，迭代器，房函数）比如有否定适配器和绑定适配器。

            6.仿函数(Functors):function object。

        \subsection{容器的选择问题}
                \subsubsection{1. 复杂度Big-oh}

                   O(1)or O(c)：常数时间（constant time）。

                   O(n)：线性时间（linear time）。

                \subsubsection{2.数据的分布、特性}

                    a. 会经常在中间安插一个数据吗？

                    b. 会经常从尾巴放数据还是常常从头部放数据？

                    c. 会经常查找一个数据吗？

        \subsection{STL容器range特点}
            容器采用“前闭后开”区间，*.end()指向最后一个元素的下一个。
        \subsection{C++11 特性}
            \subsubsection{1.C++11 range-based for statement}
\begin{lstlisting}[language=C++]
for(decl : coll){
statement
}
for(int i:{2,3,5,7,8,133}){
    std::cout<<i<<std::endl;
}
\end{lstlisting}
            \subsubsection{2.C++11 auto的使用}
\begin{lstlisting}[language=C++]
list<string> c;
...
list<string>::iterator ite;
ite = ::find(c.begin(),c.end(),target);

list<string> c;
...
auto ite= ::find(c.begin(),c.end(),target);
\end{lstlisting}
        \subsection{容器-结构与分类}
            \subsubsection{1.sequence Containers（按放入次序排列）}

                Array(fixed number of elements),vector（尾部可扩展的内存，内存是两倍增加的并会另选一块内存，只允许尾部可放入）,

                Deque （首front 尾back 首尾可扩展的内存，分段（buffer）连续（map），无内部sort，stack和queue的基础结构）,

                List （双向环状链表）,

                （C++11）Forward-List （单向链表，只允许头部可放入，尾部不是不可以只是效率太低），

                (GNU C++)slist （同Forward-List 一样，在头文件ext\\slist中）。

            \subsubsection{2.Associative Containers:(元素有key和value，适合大量快速查找，标准库内部基础为红黑树：高度平衡树)}

                Set（key和value为同一部分，key唯一）Multiset （插入为insert）,

                Map（每个节点有key 和value 两个不同部分,需要pair打包pair<keytype,valtype>(key,value)也可以c[key]=value,解包时
                \\* 用*.first 和*.second）Multimap（multi 表示key可以重复,只能用pair打包因为key可以重复）。

            \subsubsection{3.Unordered Containers:（不定序,HashTable Separate Chaining，有bucket和forward-List组成）}

                Unordered Set/Multimap,Unordered Map/Multimap。



                经验法则: 如果元素的个数大于或等于bucket的数目，需要加大bucket的个数并且重新打撒元素放入。
        \subsection{gnu c++ 4.9.2}
            \subsubsection{Generic Programming}
                特点：将datas和methods分开来，也就是说将算法和容器分开来，而两者通过迭代器来联系。
                
                而（Object-Oriented programming）是将datas和methods 结合起来。

                GP的好处：Containers和Algorithms团队可各自闭门造车，期间以Iterator 连通即可。
                
                Algorithms通过Iterators确定操作范围，并通过Iterators取用Container 元素。
            \subsubsection{algorithms的基础}
                所有algorithms，期内最终涉及元素本身的操作，无非就是比大小。
            \subsubsection{list不能用全局sort}

            \subsubsection{操作符重载Overloaded operators}
            网站\url{http://en.cppreference.com/w/cpp/operators}

            \subsubsection{模板（泛化）}
            一、类模板形如：
\begin{lstlisting}[language=C++]
template <typename T>//T未定
class complex
{
public:
    complex (T r=0,T i=0)
    :re(r),im(i)
    { }
    complex& operator += (const complex&);
    T real () const {return re;}
    T imag () const {return im;}
private:
    T re,im;
    friend complex$ __doapl (complex*,const complex&);
};

{
    complex<double> c1(2.5,6);
    complex<int> c2(5,6);
    ...
}
\end{lstlisting}

            二、函数模板（function templates）
\begin{lstlisting}[language=C++]
template <class T>//class 和 typename 相同只不过class更老点.
inline
const T& min(const T& a,const T& b)
{
    return b<a ? b:a;  //其中的'<'来自数据b和a的<操作符重载.
}
class stone
{
public:
    stone(int w,int h,int we)
    :_w(w),_h(h),_weight(we)
    { }
    bool operator<(const stone& rhs)const
    {return _weight < rhs.weight;}
private:
    int _w,_h,_weight;
};

stone r1(2,3),r2(3,3),r3;
r3 = min(r1,r2);

\end{lstlisting}
            member template成员模板

            常在构造函数这点使用成员模板。这样可以做到使用pair对直接初始化。
\begin{lstlisting}[language=C++]
template <class T1,class T2>
struct pair
{
    T1 first;
    T2 second;
    ...

    template <class U1,class U2>
    pair(const pair<U1,U2>&p)
    :first(p.first),second(p.second){ }
}
pair<Base1,Base2>p2(pair<Derived1,Derived2>());
//将一个由鲫鱼和麻雀构成的pair放进（拷贝到）一个由鱼类和鸟类构成的pair中。
\end{lstlisting}
            例如：
\begin{lstlisting}[language=C++]
template<typename _Tp>
class shared_ptr:public __shared_ptr<_Tp>
{
    ...
    template<typename _Tp1>
    explicit shared_ptr(_Tp1* __p)
    :__shared_ptr<_Tp>(__p){}
    ...
}
//一般指针的up-cast
Base1 * ptr = new Drived1; //up-cast base1为鸟类,Drived1为麻雀
//智能指针的Up-cast
shared_ptr<Base1>sptr(new Derived1);


\end{lstlisting}
            Specialization，全特化（专属）
            比如
\begin{lstlisting}[language=C++]
template <class type>
struct  __type_traits{
    typedef __true_type this_dummy_member_must_be_first;
    typedef __false_type has_trivial_default_constructor;
};
//特化如下
template<> struct __type_traits<int>{
    typedef __true_type has_trivial_default_constructor;
};
\end{lstlisting}
            specialization全特化。
\begin{lstlisting}[language=C++]
template <class Key>
struct hash{ };

template<>
struct hash<char>
{
    size_t operator()(charx)const
    {
        return x;
    }
};
\end{lstlisting}
            Partial Specialization,偏（局部）特化
\begin{lstlisting}[language=C++]

//偏特化（个数上的局部）
template<class Alloc>
class vector<bool, Alloc>
{
    ...
};
\end{lstlisting}

\begin{lstlisting}[language=C++]
//偏特化（范围上的局部）
template<class T,class Alloc=alloc>
class vector<T*>//此处将任意类型T局部为指针类型的，缩小其范围。
{
    ...
};
\end{lstlisting}
            三、Member Templates,成员模板。
        \subsection{通用库算法}
            \subsubsection{1. std::find 为循序查找}

            \subsubsection{2. std::bsearch 为二分查找}
        \subsection{容器内部算法}
            \subsubsection{1. c.sort 一般标准库中也有::sort,但当容器自己有sort时应优先使用自己的sort}
        \subsection{分配器}
            直接用不好用，因为它在释放内存时需要指明字节数。
            
            allocator$\rightarrow$ allocator.allocate$\rightarrow$operator new
            $\rightarrow$malloc。
            \subsubsection{分配器}
            推荐使用G2.9分配器alloc或G4.9$_pool_alloc$。

            gnu c++文件:$<atl_alloc.h>$。

            其它版本的allocator没有特殊的设计。

            每个malloc分配的内存都有额外的开销来记录所有分配内存的信息cookie。
            
            而因为每个容器中元素的内存大小一样，所以gnu c++对其的优化是一个容器中所有元素使用一个cookie来说明信息。

            用例：

\begin{lstlisting}[language=C++]
    vector<string,__gnu_cxx::__pool_alloc<string>>vec;
\end{lstlisting}

        \subsection{容器}
            \subsubsection{list}
                1.聪明的迭代器iterator在class list中有
\begin{lstlisting}[language=C++]
class list{
    ...
public:
    typedef __list_iterator<T,T&,T*> iterator;
    ...
}
\end{lstlisting}
\begin{lstlisting}[language=C++]
//其中__list_iterator为
template<class T,class Ref,class Ptr>
struct __list_iterator{
    typedef T value_type;
    typedef Ptr pointer;
    typedef Ref reference;
...
\end{lstlisting}
                聪明的迭代器的使用实例：
\begin{lstlisting}[language=C++]
list<Foo>::iterator ite;
...
*ite;//获得 a Foo object
ite->method();
//唤起 Foo::method()
//相当于(*ite).method();
//相当于(&(*ite))->method();
ite->field = 7;
//赋值Foo object's field
//only if field is public
//相当于(*ite).field = 7;
//相当于(&(*ite))->field = 7;
\end{lstlisting}
                2.节点设计代码
\begin{lstlisting}[language=C++]
template <class T>
struct __list_node {
typedef void* void_pointer;
void_pointer prev;
void_pointer next;
T data;
};
\end{lstlisting}
                3.涉及的$list_iterator $操作符重构
\begin{lstlisting}[language=C++]
\\prefix form
self & operator++()//有&可以连续两次使用前++
{
    node = (link_type)((*node).next);
    return *this;
}
\\postfix form
self operator++(int)//无&的原因是为了模拟整数无法连续两次后++
\\形如int i(6);i++++;（栈区变量）
{
    self tmp = *this;//不会唤起operator*因为*this已被解释为=copy的参数。=会唤起copy
    ++*this;
    return tmp;
}
\end{lstlisting}

\begin{lstlisting}[language=C++]
reference operator*() const//reference为T&
{
    return (*node).data;
}
pointer operator->()const
{
    return &(operator*());
}
\end{lstlisting}
        \subsection{代码测试经验}
            \subsubsection{1. 写测试程序时常将为了让每个程序尽量独立又可以放在一起，此时比较好的方法是可以将每个测试程序单元单独做一个命名空间}
\begin{lstlisting}[language=C++]
namespace example
{
	test_function;
}
\end{lstlisting}

            \subsubsection{2. 变量的声明和定义在正规程序一般一块放到包体里开始，写测试程序比较好的习惯是用到变量散开来并且用到时再声明的方法，同时为了变量好找一点，可以取消变量声明代码的缩进}
\begin{lstlisting}[language=C++]
void test()
{
    ...
long index=0;
    ...
}
\end{lstlisting}
    \chapter{opencv学习}            
    
    	\section{turorial}
    		\subsection{videoCapture}
    			Class for video capturing from video files,image sequences or cameras.
    			
    			refer to:
    			
    			 \url{https://docs.opencv.org/2.4/modules/highgui/doc/reading_and_writing_images_and_video.html?highlight=videocapture#VideoCapture::VideoCapture()}
    		\subsection{Mat:basic image container }
    			"Mat"is the abbreviation of "matrix",which is class with two data parts:the matrix header(containing information such as the size of the matrix,the method used for storing,at which address is the matrix stroed,and so on)and a pointer to the matrix containing the pixel values.
    			
    			Note:
    				1. Output image allocatin for OpenCV functions is automatix(unless specified otherwise).
    				
    				2. You do not need to think about memory management with OpenCVs C++ interface.
    				
    				3. The assignment operator and the copy constructor only copies the header.
    				
    				4. The underlying matrix of an image may be copied using the clone() and copyTo() functions.
    				
    				5. To specify the data type to use for storing the elements and the number of channels per matrix point, we have multiple definitions constructed according to the following convention:
 \begin{lstlisting}[language=C++]
 CV_[The number of bits per item][Signed or Unsigned]
 [Type Prefix]C[The channel number]
 \end{lstlisting}
    				
    				For instance, $CV_8UC3$ means we use unsigned char types that are 8 bit long and each pixel has three of these to form the three channels.
    				
    			refer to: \url{https://en.wikibooks.org/wiki/LaTeX/PGF/TikZ#Nodes}
    			
    			使用方法:
    			
    			\subsubsection{1、使用准备}
    			
\begin{lstlisting}[language=C++]
using namespace cv;
\end{lstlisting}
				
				\subsubsection{2、Mat的声明}
				
\begin{lstlisting}[language=C++]
Mat m =  Mat(rows,cols,type);

Mat m = Mat(Size(width,height),type);

Mat A = Mat(3,4,CV_32FC1);
\end{lstlisting}
				\subsubsection{3、Mat的赋值}
				
\begin{lstlisting}[language=C++]
vector<Point3f>v;//suppose it is already full

Mat m1 = Mat(v,true);//boolean value true is necessary in order to copy data from c to m1

CvMat *p1 = m1;//可能存在问题

Mat m2 = Mat(p1);
\end{lstlisting}
				\subsubsection{4、Mat 之间的运算}
\begin{lstlisting}[language=C++]
Mat C = 2*A*B;
Mat C = C.inv();//now C is its own inverse matrix
Mat D = A.t();//D is the transposed matrix of A
Mat a = Mat(4,1,CV_32FC3);//a is 4x1,3 channels
Mat b = a.reshape(1);//b is 4x3,1 channel
\end{lstlisting}
				\subsubsection{5、单通道Mat元素读写}
\begin{lstlisting}[language=C++]
Mat a = Mat(4,3,CV_32FC1);
float elem_a = a.at<float>(i,j);//access element aij,with i from 0 to rows-1 and j from 0 to cols-1.
Point p = Point(x,y);
float elem_a = a.at<float>(p);//warning:y ranges from 0 to rows-1 and x from 0 to cols-1
\end{lstlisting}
				\subsubsection{6、多通道Mat元素读写}

参考：

\url{http://www.360doc.com/content/13/0415/16/10724725_278435687.shtml}

\begin{lstlisting}[language=C++]
//模板
template<typename _Tp> _Tp& at(int y,int x);//cxcore.hpp(868)
template<typename _Tp>const _Tp&at(int y,int x)const; //cxcore.hpp(870)
template<typename _Tp>_Tp& at(Point pt); //cxcore.hpp(869)
template<typename _Tp>const _Tp&at(Point pt)const; //cxcore.hpp(871)
//defineded in cxmat.hpp
typedef Vec<float,2>Vec2f;//cxcore.hpp(254)
//其中Vec为向量模板类，上述代码段中类型为float,向量的dim = 2;

//we can access the element like this:
Mat m(Size(3,3),CV_32FC2);
Vec2f&elem = m.at<Vec2f>(row,col);// or m.at<Vec2f>(Point(col,row));
elem[0] = 1212.0f;
elem[1] = 326.0f;
float c1 = m.at<Vec2f>(row,col)[0];//or m.at<Vec2f>(Point(col,row));
float c2 = m.at<Vec2f>(row,col)[1];
m.at<Vec2f>(row,col)[0] = 1986.0f;
m.at<Vec2f>(row,col)[1] = 326.0f;

\end{lstlisting}
				\subsubsection{7、选取Mat上指定区域方法}
\begin{lstlisting}[language=C++]
Mat src;
Rect rect;
Mat dst = src(rect);
或者
Mat dst(src,rect);
\end{lstlisting}
				\subsubsection{8、深浅拷贝}
				
				copy:浅拷贝
				
				clone和copyto：深拷贝
				\subsubsection{9、zeros and ones}
\begin{lstlisting}[language=C++]
C++: static MatExpr Mat::zeros(int rows, int cols, int type)
C++: static MatExpr Mat::zeros(Size size, int type)
C++: static MatExpr Mat::zeros(int ndims, const int* sizes, int type)
参数
ndims – 数组的维数。
rows–行数。
cols  –列数。
size–替代矩阵大小规格Size(cols, rows)的方法。
sizes– 指定数组的形状的整数数组。
type– 创建的矩阵的类型。
\end{lstlisting}
ones和zeros类似。
			   \subsubsection{10、cvmat、mat and Iplimage}
			   留空待填！
			   \subsubsection{push back}
			   
\begin{lstlisting}[language=C++]
			   C++: template<typename T> void Mat::push_back(const T& elem)
			   
			   The methods add one or more elements to the bottom of the matrix. They emulate the corresponding method of the STL vector class. When elem is Mat , its type and the number of columns must be the same as in the container matrix. to push elements by rows.
\end{lstlisting}

				\subsection{Rect:class}
\begin{lstlisting}[language=C++]
Rect rect(100,50,50,100);

Rect rect(左上基准水平坐标,左上基准垂直坐标,水平向右扩展像素个数,垂直向下扩展像素个数);

rect.area();//area
rect.size();//Size(尺寸)类的数据成员是width和height

rect.tl();//左上,top and left
rect.br();//右下,bottom and right

rect.width();
rect.height();

rect.contains(Point(x,y));//判断rect是否包含Point(x,y)点

rect = rect1 & rect2;//交
rect = rect1 | rect2;//并

rect = rect + Point(-100,100);//平移
rect = rect + Size(-100,100);//缩放，左上顶点不变，宽度-100,高度 +100
\end{lstlisting}
			\subsection{CvvImage:class}
			可以在MFC(microsoft fundation classes)的窗口中显示image。
			\subsection{Point,Size,Scalar：class}
			
			\includegraphics[width=12cm, height=7cm]{psrs}
			
			\subsubsection{Scalar}
\begin{lstlisting}[language=C++]		
typedef struct CvScalar { double val[4] } CvScalar;
\end{lstlisting}
			\subsubsection{Point}
\begin{lstlisting}[language=C++]
typedef Point_<int>      Point2i;  
typedef Point2i          Point;  
typedef Point_<float>    Point2f;  
typedef Point_<double>   Point2d;  
typedef Point3_<int>     Point3i;  
typedef Point3_<float>   Point3f; 
\end{lstlisting}
			\subsection{Function}
				\subsubsection{cv::absdiff}
				Abstract Difference.
				
				Calculates the per-element absolute difference between two arrays or between an array and a scalar.
				
				输出为一个array,而不是一个scalar。
\begin{lstlisting}[language=C++]		
void cv::absdiff	(	InputArray 	src1,
InputArray 	src2,
OutputArray 	dst 
)	
\end{lstlisting}
    			\subsubsection{namedWindow:Creates a window}
\begin{lstlisting}[language=C++]
C++: void namedWindow(const string& winname, 
int flags=WINDOW_AUTOSIZE )
\end{lstlisting}
flip:Filps a 2D array.
\begin{lstlisting}[language=C++]
C++: void flip(InputArray src, 
OutputArray dst, 
int flipCode)
\end{lstlisting}

$$dst_{ij}=
\begin{cases}
src_{src.rows-i-1,j}& \text{if filpCode = 0}\\
src_{i,src.cols-j-1}& \text{if filpCode > 0}\\
src_{src.rows-i-1,src.cols-j-1}& \text{if filpCode <0}
\end{cases}$$
	
    		\subsection{Algorithm}

    			\subsubsection{cvtColor}
    			Converts an image from one color space to another.
\begin{lstlisting}[language=C++]
void cvtColor(InputArray src, 
OutputArray dst, 
int code, 
int dstCn=0 )

\end{lstlisting}
    			Parameters:	
    			
				src $–$ input image: 8$-$bit unsigned, 16$-$bit unsigned $( CV_16UC... )$,
				
				or single$-$precision floating$-$point.
				
				dst $–$ output image of the same size and depth as src.
				
				code $–$ color space conversion code (see the description below).
				
				dstCn $–$ number of channels in the destination image; if the parameter is 0,
				
				the number of the channels is derived automatically from src and code .
				
    			$$RGB[A] to Gray: Y\leftarrow 0.299\times R+0587\times G + 0.114\times B$$
    			$$Gray to RGB[A]: R\leftarrow Y,G\leftarrow Y,B \leftarrow Y,A\leftarrow max(ChannelRange)$$
    			
    			其它转换见网站：\url{http://docs.opencv.org/2.4/modules/imgproc/doc/miscellaneous_transformations.html?highlight=cvtcolor#cvtcolor}
    			
    			\subsubsection{GaussianBlur}
    			Blurs an image using a Gaussian filter.
  \begin{lstlisting}[language=C++]
  void GaussianBlur(InputArray src, 
  OutputArray dst, 
  Size ksize,			 
  double sigmaX, 
  double sigmaY=0, 
  int borderType=BORDER_DEFAULT )

 \end{lstlisting}
 				sigmaX – Gaussian kernel standard deviation in X direction.//标准差，波动系数，决定了正态分布概率密度
 				
 				sigmaY – Gaussian kernel standard deviation in Y direction.//函数的胖瘦
 				
    			gaussian noise：is statistical noise having a probability density function (PDF) equal to that of the normal distribution.
    			
    			Gaussian blur is a low-pass filter, attenuating high frequency signals.
    			
    			The probability density function p of a Gaussian random variable z is given by:
    			$$\varphi_{G}(z)= \frac{1}{\sigma\sqrt{2\pi}e^{-\frac{(z-u)^2}{2\sigma^2}}}$$
    			
    			个人理解：高斯过滤器原理首先确定估计点将其固定在Normal Curve的期望处，然后给周围附近的点处的像素值赋予符合归一后正态分布的概率，然后求其期望值（期望为$\infty$抽样后的平均值，因此不严谨地说高斯过滤也是一个平滑滤波）。
    			
    			越近越出现的概率越大。
    			
    			（考虑一维的正态分布，且$\omega = \mathbf{R}$，可以视估计点周围一定精度下形成的集合$\omega 1$到$\omega$映射为一个随机变量来思考），另外一点，求期望值其实可以视为概率密度曲线和自变量坐标轴之间的卷积。
    			
    			参考：\url{http://blog.csdn.net/yangyangyang20092010/article/details/48576007}
    			
    			Each pixel's new value is set to a weighted average of that pixel's neighborhood.
    			
    			参考：\url{https://en.wikipedia.org/wiki/Gaussian_blur}
    			
    			\subsubsection{Canny}
    			Finds edges in an image.
 \begin{lstlisting}[language=C++]
 C++: void Canny(InputArray image, 
 OutputArray edges,
 double threshold1,   			
 double threshold2, 
 int apertureSize=3, 
 bool L2gradient=false )

 \end{lstlisting}
  				apertureSize:aperture size for the Sobel() operator.
  				
			    L2gradient：to calculate the image gradient magnitude.//梯度长度计算范数的选择。
 
    			算法主要步骤：
    			
    			1、图像Gray化.
    			
    			2、对图像进行高斯滤波，让图像变平滑。
    			
    			3、计算Gray图上灰度值变化的梯度。
    			
    			梯度公式：$$grad\mathit{t} = \nabla\mathit{t}=\frac{\alpha \mathit{t}}{\alpha \mathit{x}}+\frac{\alpha \mathit{t}}{\alpha \mathit{y}}+\frac{\alpha \mathit{t}}{\alpha \mathit{z}}$$
    			
    			梯度可以理解为一种空间导数，只不过它由各方向上的偏导数组成。
    			
    			各点梯度数值近似计算：
    			
    			a.Roberts算子，为一个二维算子。
    			
    			b.Sobel算子，为一个三维算子。
    			
    			c.Prewitt算子，为一个三维算子。
    			
    			d.Canny算子，为一个二维算子。
    			
    			各个算子的共性是通过对目标点周围的像素进行特别的代数运算分别计算出X方向和Y方向的偏导数。
    			
    			4.对梯度幅值进行非极大值抑制
    			
    			通俗意义上是指寻找像素点局部最大值，将非极大值点所对应的灰度值置为0，这样可以剔除掉一大部分非边缘的点，类似于一堵墙的两边的梯度都比墙附近的荒地的梯度要大。
    			
    			参考：\url{http://blog.csdn.net/likezhaobin/article/details/6892176}
    			
    			5.用双阈值算法检测和连接边缘
    			
    			高滤低连，高的阈值来滤取合格的边缘，低的那个阈值来增强边缘的细节。
    			
    			\subsubsection{findContours}
    			Finds contours in a binary image.
    			
 \begin{lstlisting}[language=C++]
 void findContours(InputOutputArray image,
      OutputArrayOfArrays contours, 
      OutputArray hierarchy, 
      int mode,
      int method,
      Point offset=Point())
    			hierarchy 
 \end{lstlisting}
    	\section{machine learning}
    		\subsection{K-nearest-neighbors}
    			定位：lazy learning algorithm，所谓懒惰算法指的是，直到有了新的测试样本，该算法才开始依据训练样本进行样本的预测处理工作，也就是说该算法事先不会对训练样本进行任何的处理，只会“懒散”的等待测试样本的到来，然后才开始工作。
    			\subsubsection{M distance}
    			协方差矩阵的逆：逆矩阵的原因是相当于除去scale对距离的影响,想想一维的情况就应该能理解了，比如说同样距离都是3,但是对于方差大的数据,这个距离就算小了,所以要用距离再除以方差,高维情况就是协方差阵的逆了。
    			
    			\paragraph{矩阵的逆的意义}
    			那到底怎么才能准确地描述未知个体与已知个体的相似性呢？在此，我们不妨再次假设样本容量n=m，且特征值矩阵X是可逆的，也就是说样本中的个体是线性无关的。
    			
    			我们知道逆矩阵有这样的性质：
    			$X^{-1}*X = E$
    			
    			这对我们有什么启发呢？假设未知个体的特征值向量为x，x可以用X的m个线性无关列向量（已知个体的特征值向量）表示：
    			$x=a_1*X_1+a_2*X_2+...+a_m*X_m$
    			
    			此时将X的逆矩阵乘以未知个体x，可得：
    			
    			$$X^{-1}*x = a_1 * X^{-1}*X_1 + a_2*X^{-1}*X_2 +...+a_m*X^{-1}*X_m$$
    											$$
    			\left[
    			\begin{matrix}
    			a_1 \\
    			0\\
    			\vdots\\
    			0\\
    			\end{matrix}
    			+
    			\begin{matrix}
    			0\\a_2\\ \vdots \\0
    			\end{matrix}
    			+\cdots+
    			\begin{matrix}
    			0\\0\\ \vdots \\a_m
    			\end{matrix}
    			=
    			\begin{matrix}
    			a_1\\a_2\\ \vdots \\ a_m
    			\end{matrix}
    			\right]
    			$$
    			根据上式我们可以看到，在已知个体是线性无关的前提下，若未知个体能包含ai份第i个已知个体的特征，则其与第i个已知个体的近似度就为ai。
    			
    			显然，这样的近似表示方法，在线性模型中才是准确的。
    			
    			如果样本的容量n大于m，我们该如何处理呢？假设X的秩仍然等于m，但由于X不是方阵，无法求解逆矩阵。
    			
    			此时我们可以将原线性模型改写成：
    			
    			$$Y*X^T = W*X*X^T + e*X^T$$
    			
    			此时，X乘以X的转置则变成了m维的方阵，由于X的秩为m，X与X转置的乘积的秩也为m，即可逆。
    			
    			此时我们需要将Y与X的转置的乘以看成新的目标值向量，X与X转置的乘积看成新的已知个体的特征值矩阵，e与X转置的乘积看成新的误差向量。
    			
    			不难看到，原始问题与新问题的解(回归问题的解通常是求权值向量)是“等价”的。
    			
    			在新问题中，特征值矩阵是方阵且可逆，这样便可通过求解新问题来解决原始问题了。
    			
    			\paragraph{M distance}
    			考虑:$(x-\mu)^T S^{-1} (x-\mu)$,其中$S$为多变量向量$x=(x_1,x_2,\cdots,x_m)^T$的协方差矩阵。
    			
    			首先将$S^{-1} (x-\mu)$即为在协方差$S$尺度下的$x-\mu$的特征值向量。
    			
    			$$S^{-1}*(x-\mu) = a_1 * S^{-1}*S_1 + a_2*S^{-1}*S_2 +...+a_m*S^{-1}*S_m$$
    			
    			$S_1、S_2、\cdots、S_m$为协方差矩阵$S$的特征向量，其意义是什么？观察协方差矩阵
    			
    			$$\left[
    			\begin{matrix}
    			Cov(X_1,X_1) && Cov(X_1,X_2) && \cdots && Cov(X_1,X_n) \\
    			Cov(X_2,X_1) && Cov(X_2,X_2) && \cdots && Cov(X_2,X_n) \\
    			\vdots && \vdots && \cdots && \vdots \\
    			Cov(X_n,X_1) && Cov(X_n,X_2) && \cdots && Cov(X_n,X_n) \\
    			\end{matrix}
    			\right]$$
    			
    			
    			$$
    			\left[
    			\begin{matrix}
    			a_1 \\
    			0\\
    			\vdots\\
    			0\\
    			\end{matrix}
    			+
    			\begin{matrix}
    			0\\a_2\\ \vdots \\0
    			\end{matrix}
    			+\cdots+
    			\begin{matrix}
    			0\\0\\ \vdots \\a_m
    			\end{matrix}
    			=
    			\begin{matrix}
    			a_1\\a_2\\ \vdots \\ a_m
    			\end{matrix}
    			\right]
    			$$
    			
    			可知$S_1$为$[Cov(X_1,X_1),\cdots,Cov(X_n,X_1)]^T$的特征向量，而$[Cov(X_1,X_1),\cdots,Cov(X_n,X_1)]^T$是所有随机变量与随机变量$X_1$的协方差形成的向量，是不是会下意识的认为和$X_1$必定有关，其实是这样的想法是不正确的。
    			
    			正确解释：
    			
    			One of the most intuitive explanations of eigenvectors of a covariance matrix is that they are the directions in which the data varies the most. 
    			
    			(More precisely, the first eigenvector is the direction in which the data varies the most, the second eigenvector is the direction of greatest variance among those that are orthogonal (perpendicular) to the first eigenvector, the third eigenvector is the direction of greatest variance among those orthogonal to the first two, and so on.)
    			
    			Here is an example in 2 dimensions [1]:
    			
    			\includegraphics[width=14cm, height=9cm]{convariance1}
    			
    			Each data sample is a 2 dimensional point with coordinates x, y. 
    			
    			The eigenvectors of the covariance matrix of these data samples are the vectors u and v; u, longer arrow, is the first eigenvector and v, the shorter arrow, is the second. (The eigenvalues are the length of the arrows.) 
    			
    			As you can see, the first eigenvector points (from the mean of the data) in the direction in which the data varies the most in Euclidean space, and the second eigenvector is orthogonal (perpendicular) to the first.
    			
    			It's a little trickier to visualize in 3 dimensions, but here's an attempt [2]:
    			
    			\includegraphics[width=14cm, height=9cm]{convariance2}
    			
    			In this case, imagine that all of the data points lie within the ellipsoid.
    			
    			 v1, the direction in which the data varies the most, is the first eigenvector (lambda1 is the corresponding eigenvalue). 
    			 
    			 v2 is the direction in which the data varies the most among those directions that are orthogonal to v1.
    			 
    			  And v3 is the direction of greatest variance among those directions that are orthogonal to v1 and v2 (though there is only one such orthogonal direction). 
    			
    			所以第一个特征向量$S_1$在样本协方差最大的方向下，所以$a_1 S^{-1}*S_1$中的$a_1$为向量$X$在$S_1$方向上的特征值，它是$X$在协方差矩阵$S$(这个矩阵由样本决定！)下从$S_1$视角下的特征值。
    			
    			再考察$X^T S^{-1} X$是什么鬼？
    			
    			设$A = [a_1,a_2,\cdots,a_n]^T$首先分解$X = a_1*X_1+a_2*X_2+\cdots+a_n*X_n$因为$S^{-1}X = [a_1,a_2,\cdots,a_n]^T$所以$X^T S^{-1} X = a_1*X_1^T*A + a_2*X_2^T*A + \cdots + a_n*X_n^T*A$
    			
    			\includegraphics[width=14cm, height=9cm]{Mdistance}
    			
    			\subsubsection{knn原理}
    			有了马氏距离就很好解释，顾名思义,KNN(k-nearest-neighbors),找k个最近的亲戚,按远近分配weighted ratio,并每人发一张vote,再根据投票数和weighted ratio,来选择类别。
    			\subsubsection{opencv knn source analysis}
    			讨论了半天，查看了opencv k-nearest neighbors源码，发现它度量测试样本和样本集中样本的距离没有用马氏距离，而是使用了欧式距离(即2-范数)，欧式距离为马氏距离在协方差矩阵为单元矩阵时的一种特殊情况，它和更一般的马氏距离相比计算更加简便，还有一个原因在于各维之间不相关。
    			
    			源码距离度量核心部分：
    			
%    			\includegraphics[width=14cm, height=9cm]{knndistance}
    			
    			位置：$\\opencv\\sources\\modules\\ml\\src\\knearest.cpp$中的$findNearestCore$中。
    			
    	\section{书:OpenCV2计算机视觉编程手册}
    		\subsubsection{lib布局}
    		
    		1、$opencv_core$：核心功能，底层数据结构和算法函数。
    		
    		2、$opencv_imgproc$
    		
    		
    		：图像处理函数。
  
    		3、$opencv_highgui$：读写图像及视屏的函数，以及操作图形用户界面函数。
    		
    		4、$opencv_features2d$：包含兴趣点检测子、描述子以及兴趣点匹配框架。
    		
    		5、$opencv_calib3d$：相机标定、双目几何估算以及立体视觉函数。
    		
    		6、$opencv_objdetect$：物体检测函数，如脸部与行人检测。
    		
    		\subsection{像素的操作}
    		1、像素的存取
    			
    	\section{数字图像处理}
    		\subsection{基本概念理解}
    			\subsubsection{采样}
    			一幅图像的每个像素位置上测量灰度值。
    			
    			\subsubsection{量化}
    			将测量的灰度值用一个整数来表示。
    			
    			\subsubsection{灰度值}
    			表示颜色的深浅，对一副彩色图像，RGB三个channel有各自的灰度值，Gray也有其灰度值，RGB和Gray之间的转换请见cvtColor函数说明。
    			
    			\subsubsection{对比度}
    			指一副图像中灰度反差的大小。
    			
    			\subsubsection{分辨率}
    			opencv 这边为ppi(pixel per inch),一般用在online上。
    			
    			dpi(dot per inch),一般用在纸质打印。
    			
    			屏幕15.6寸，高：7.68inch，宽：13.66inch，系统分辨率1366x768，可以计算物理尺寸与像素的比例为100 像素/inch，即100 ppi。
    			
    			
    			图像的物理宽度(英寸为单位)等于像素宽度除以水平分辨率。 例如，像素宽度为 216、水平分辨率为 ：72 点/英寸 的图像，它的物理宽度：216/72= 3 英寸。 也同样适用于像素高度和物理高度。
    			
    		\subsection{灰度直方图}
    			1.阈值面积函数A(D):A is abbreviation of acreage,and D is a degree of gray.
    			
    			阈值面积函数类似于概率分布函数$(CDF:cumultive distributin function)$。
    			
    			2.直方图H(D):H is abbreviation of histogram.
    			$$H(D) = \lim_{\Delta\rightarrow 0}\frac{A(D)-A(D+\Delta D)}{\Delta D} = - \frac{d}{dD} A(D)$$
    			归一化后直方图类似于概率密度函数$(PDF:probablity density function)$。
    			
    			3.综合光密度IOD：integrated optical density
    			$$IOD=\int_0^a\int_0^b D(x,y)dxdy$$
    			类似图像的“质量”。
    			
    			
    \chapter{wxWidgets学习}
    		以wxframe类为框架，可以添加一系列event来捕捉用户触发的事件，还有一点是线程用指针变量来指定(此处具体待扩展)。
    \chapter{几何}
    
    	\section{齐次坐标的理解}
    		内容参考：\url{http://blog.csdn.net/janestar/article/details/44244849}		
    		
    		因为博文讲得非常透彻，我在此将博文经典之处加以记录。
    		
    		问题：两条平行线可以相交于一点？
    		
    		在欧氏几何空间，同一平面的两条平行线不能相交，这是我们都熟悉的一种场景。然而，在透视空间里面，两条平行线可以相交，例如：火车轨道随着我们的视线越来越窄，最后两条平行线在无穷远处交于一点。
    		
    		欧氏空间（或者笛卡尔空间）描述2D/3D几何非常适合，但是这种方法却不适合处理透视空间的问题实际上，欧氏几何是透视几何的一个子集合，2维笛卡尔坐标可以表示为$(x,y)$。
    		
    		如果一个点在无穷远处，这个点的坐标将会$()$，在欧氏空间，这变得没有意义。平行线在透视空间的无穷远处交于一点，但是在欧氏空间却不能，数学家发现了一种方式来解决这个问题。
    		
    		方法：齐次坐标(简而言之，齐次坐标就是用N+1维来代表N维坐标)
    		
    		我们可以在一个2D笛卡尔坐标末尾加上一个额外的变量w来形成2D齐次坐标，因此，一个点$(X,Y)$在齐次坐标里面变成了$(x,y,w)$，并且有$X = \frac{x}{w}$ $Y=\frac{y}{w}$
    		例如，笛卡尔坐标系下$(1,2)$的齐次坐标可以表示为$(1,2,1)$，如果点$(1,2)$移动到无限远处，在笛卡尔坐标下它变为$(\infty,\infty)$，然后它的齐次坐标表示为$(1,2,0)$，因为$(1/0, 2/0) = (\infty,\infty)$，我们可以不用$\infty$来表示一个无穷远处的点了。
    		
    		为什么叫齐次坐标？
    		
    		我们把齐次坐标转化为笛卡尔坐标的方法是前面n-1个坐标分量分别除以最后一个分量即可。
    		
    		$$\frac{(x,y,w)}{Homogeneous} \Leftrightarrow \frac{(\frac{x}{w},\frac{y}{w})}{Cartesian}$$
    		
    		转化齐次坐标到笛卡尔坐标的过程中，我们有一个发现，例如：
    		\begin{align*}
    		& (1,2,3) \Rightarrow (\frac{1}{3},\frac{2}{3}) \\
    		& (2,4,6) \Rightarrow (\frac{2}{6},\frac{4}{6}) = (\frac{1}{3},\frac{2}{3}) \\
    		& (4,8,12) \Rightarrow (\frac{4}{12},\frac{8}{12}) = (\frac{1}{3},\frac{2}{3}) \\
    		& ... \\
    		& (1a,2a,3a) \Rightarrow (\frac{1a}{3a},\frac{2a}{3a}) = (\frac{1}{3},\frac{2}{3})\\
    		\end{align*}
    		
    		你会发现$(1, 2, 3), (2, 4, 6)$ 和$(4, 8, 12)$对应同一个$Euclidean point (1/3, 2/3)$，任何标量的乘积，例如$(1a, 2a, 3a) $对应 笛卡尔空间里面的$(\frac{1}{3}, \frac{2}{3})$ 。
    		
    		因此，这些点是“齐次的”，因为他们代表了笛卡尔坐标系里面的同一个点。换句话说，齐次坐标有规模不变性。
    		
    		证明：两条直线可以相交
    		
    		考虑如下方程组：
    		$$
    		\begin{cases}
    		Ax+By+C=0& \text{}\\
    		Ax+By+D=0& \text{}
    		\end{cases}$$
    		我们知道在笛卡尔坐标系里面，该方程组无解，因为C ≠ D,如果C=D,两条直线就相同了。
    		
    		让我们在透视空间里面，用齐次坐标$\frac{x}{w}$, $\frac{y}{w}$代替x ,y,
    		
    		$$
    		\begin{cases}
    		A\frac{x}{w}+B\frac{y}{w}+C=0& \text{}\\
    		A\frac{x}{w}+B\frac{y}{w}+D=0& \text{}
    		\end{cases}
    		\Rightarrow
    		\begin{cases}
    		Ax+By+Cw=0& \text{}\\
    		Ax+By+Dw=0& \text{}
    		\end{cases}
    		$$
    		
    		现在我们有一个解$(x, y, 0)$，两条直线相交于$(x, y, 0)$，这个点在无穷远处。
    \chapter{工具使用}
    	\section{cmake}
    		\subsection{cmake编译opencv and opencv contribute的经验教训}
			使用opencv版本:official release 3.1.0
			
			opencv contrib版本:3.3.1
			
			使用cmake编译，出现有些文件无法download。
    		\begin{lstlisting}[language=C++]
在cmake中会出现下载错误，导致config失败。
看cmake源代码知道ocv_download这个函数在使用的时候，错把PACKAGE写成filename.
修改后再次config,generate成功。
opencv_contrib\modules\dnn\cmake\OpenCVFindLibProtobuf.cmake

32 行改为
ocv_download(PACKAGE "protobuf-cpp-3.1.0.tar.gz"
opencv_contrib\modules\dnn_modern\CMakeLists.txt
20行改为
ocv_download(PACKAGE "v1.0.0a3.tar.gz"

opencv_contrib\modules\xfeatures2d\cmake\download_boostdesc.cmake
22行改为
ocv_download(PACKAGE ${name_${id}}

opencv_contrib\modules\xfeatures2d\cmake\download_vgg.cmake
16行改为
ocv_download(PACKAGE ${name_${id}}
    		\end{lstlisting}
    		
    		通过以上修改，cmake可以通过configure和generate生产opencv.sln,但是vistual studio在编译时出现了很多错误。
    		
    		经查找原因发现是opencv的版本和opencv contirb的版本不一致导致以上的错误，所以将opencv的版本改为3.3.1后，cmake configure和generate都正常，而且vistual studio也可以正常build。
    		
    		以下是一个大牛写的tutorial:\url{https://putuyuwono.wordpress.com/2015/04/23/building-and-installing-opencv-3-0-on-windows-7-64-bit/}
    		
    		超棒的一个tutorial,但还是得强调一下Opencv和opencv contrib一起编译时需要版本一致。
    		
    	\section{portable GIMP}
    		执行文件在bin文件夹中，功能类似于photoshop，开源绿色软件。
    		\subsection{直方图查看}
    		将原图扔到GIMP窗口中，使用GIMP的直方图功能可以看到原图的直方图，并且还可以简单对原图的直方图设置阈值来查看threshold后的效果图。
    	\section{linux}
    		比较实在的linux博主\url{http://blog.chinaunix.net/uid-23069658-id-4028681.html}
    		\subsection{编译与链接pkg-config}
    		前段时间走歪路时，使用linux系统来编译安装GTK+，在编译和链接时遇到了不少麻烦，此处予以记录。
    		
    		参考：\url{http://www.cnblogs.com/s_agapo/archive/2012/04/24/2468925.html}
    		
    		前提假设：如果库的头文件不在 /usr/include 目录中，那么在编译的时候需要用 -I 参数指定其路径。由于同一个库在不同系统上可能位于不同的目录下，用户安装库的时候也可以将库安装在不同的目录下，所以即使使用同一个库，由于库的路径的不同，造成了用 -I 参数指定的头文件的路径也可能不同，其结果就是造成了编译命令界面的不统一。
    		
    		问题：编译和连接界面不统一。
    		
    		解决方法：事先把库的位置信息等保存起来，需要的时候再通过特定的工具将其中有用的信息提取出来供编译和连接使用。这样，就可以做到编译和连接界面的一致性。
    		
    		工具：pkg-config，pkg-config 是通过库提供的一个 .pc 文件获得库的各种必要信息的，包括版本信息、编译和连接需要的参数等。
    		
\begin{lstlisting}[language=C++]
prefix=/opt/gtk/
exec_prefix=${prefix}
libdir=${exec_prefix}/lib
includedir=${prefix}/include

glib_genmarshal=glib-genmarshal
gobject_query=gobject-query
glib_mkenums=glib-mkenums

Name: GLib
Description: C Utility Library
Version: 2.12.13
Libs: -L${libdir} -lglib-2.0 
Cflags: -I${includedir}/glib-2.0 -I${libdir}/glib-2.0/include 
\end{lstlisting}
    		
    		introduction：
    		The pkgconfig package contains tools for passing the include path or library paths to build tools during the make file execution.
    		
    		pkg\underline{\hspace{0.5em}}config is a function that returns meta information for the specified library.
    		
    		The default setting for PKG\underline{\hspace{0.5em}}CONFIG\underline{\hspace{0.5em}}PATH is / usr/ lib/ pkgconfig because of the prefix we use to install pkgconfig .You may add to PKG\underline{\hspace{0.5em}}CONFIG\underline{\hspace{0.5em}}PATH by exporting additional paths on your system where pkgconfig files are installed. Note that PKG\underline{\hspace{0.5em}}CONFIG\underline{\hspace{0.5em}}PATH is only needed when compiling packages, not during run\underline{\hspace{0.5em}}time.
    		
    		.pc文件的path：*/lib/pkgconfig。
    		
			使用：
			使用 pkg-config 的 --cflags 参数可以给出在编译时所需要的选项，而--libs 参数可以给出连接时的选项。例如，假设一个 sample.c 的程序用到了 Glib 库，就可以这样编译：
			
			$$ gcc -c pkg-config --cflags glib-2.0 sample.c$$
			
			然后这样连接：
			
			$$ gcc sample.o -o sample pkg-config --libs glib-2.0`$$
			
			或者上面两步也可以合并为以下一步：
			
			$$ gcc sample.c -o sample pkg-config --cflags --libs glib-2.0`$$
			
			pkg-config 如何知道要到哪里去寻找此 .pc 文件？
			
			方法一：Linux 系统把 /lib 和 /usr/lib 两个目录作为默认的库搜索路径，在默认的库搜索路径下搜索。(运行时和静态都ok)
			
 			方法二：通过终端窗口的环境变量PKG\underline{\hspace{0.5em}}CONFIG\underline{\hspace{0.5em}}PATH(原生，最直接)。
			
			注意：环境变量的设置只对当前的终端窗口有效，所以当系统重新启动、或者新开一个终端窗口之后，如果想使用新安装的 GTK+ 库，需要如上面那样重新设置PKG\underline{\hspace{0.5em}}CONFIG\underline{\hspace{0.5em}}PATH。
			
			为了使库的设置变得简单一些，可以把下面的这两句设置保存到一个文件中（比如set\underline{\hspace{0.5em}}gtk-2.10文件）:
			
			$$export PKG_CONFIG_PATH=/opt/gtk/lib/pkgconfig$$
			$$export LD_LIBRARY_PATH=/opt/gtk/lib$$，将LD\underline{\hspace{0.5em}}LIBRARY\underline{\hspace{0.5em}}PATH也考虑进来的原因方法三有解释。
    		
    		之后，就可以用下面的方法进行库的设置了（其中的 source 命令也可以用 . 代替）：
    		
    		$$ source set_gtk-2.10 $$
    		
    		只有在用新版的 GTK+ 库开发应用程序、或者运行使用了新版 GTK+ 库的程序的时候，才有必要进行上述设置。
    		
    		方法三：通过动态库连接LD\underline{\hspace{0.5em}}LIBRARY\underline{\hspace{0.5em}}PATH和/etc/ld.so.conf 文件。
    		
    		设置库文件的搜索路径有下列两种方式，可任选其一使用：
    		
    		在环境变量 LD\underline{\hspace{0.5em}}LIBRARY\underline{\hspace{0.5em}}PATH中指明库的搜索路径。
    		
    		在 /etc/ld.so.conf 文件中添加库的搜索路径。
    		
    		将自己可能存放库文件的路径都加入到$/etc/ld.so.conf$中是明智的选择。
    		
    		添加方法也极其简单，将库文件的绝对路径直接写进去就OK了，一行一个。例如：
    		
\begin{lstlisting}[language=C++]
/usr/X11R6/lib
/usr/local/lib
/opt/lib
\end{lstlisting}
    		
    		需要注意的是：第三种搜索路径的设置方式对于程序连接时的库（包括共享库和静态库）的定位已经足够了，但是对于使用了共享库的程序的执行还是不够的。
    		
    		这是因为为了加快程序执行时对共享库的定位速度，避免使用搜索路径查找共享库的低效率，所以是直接读取库列表文件 /etc/ld.so.cache 从中进行搜索的。
    		
    		/etc/ld.so.cache 是一个非文本的数据文件，不能直接编辑，它是根据 /etc/ld.so.conf 中设置的搜索路径由 /sbin/ldconfig 命令将这些搜索路径下的共享库文件集中在一起而生成的(ldconfig 命令要以 root 权限执行)。
    		
    		因此，为了保证程序执行时对库的定位，在 /etc/ld.so.conf 中进行了库搜索路径的设置之后，还必须要运行 /sbin/ldconfig 命令更新 /etc/ld.so.cache 文件之后才可以。
    		
    		ldconfig ,简单的说，它的作用就是将/etc/ld.so.conf列出的路径下的库文件 缓存到/etc/ld.so.cache 以供使用。
    		
    		因此当安装完一些库文件，(例如刚安装好glib)，或者修改ld.so.conf增加新的库路径后，需要运行一下 /sbin/ldconfig使所有的库文件都被缓存到ld.so.cache中。
    		
    		方法四： -L 参数显式指定。因为用 -L 设置的路径将被优先搜索，所以在连接的时候通常都会以这种方式直接指定要连接的库的路径。
    		
    		痛苦的教训，库文件链接问题！
    		
    	\section{msys2}
    		\subsection{introduction}
    			MSYS2 consists of three subsystems and their corresponding package repositories, msys2, mingw32, and mingw64.
    			
				\url{https://github.com/msys2/msys2/wiki}
    		\subsection{download}
    		The packages in msys2 are named just like on a Linux distribution, the packages in mingw are prefixed by either $mingw-w64-i686- for 32-bit packages, or mingw-w64-x86_64- for 64-bit packages.$
    		
    			website：\url{http://blog.csdn.net/likezhaobin/article/details/6892176}
    		\subsection{遇到问题}
    		首先利用msys2可以下载到mingw32编译后的package,比如通过package manager(pacman)下载mingw32编译后的opencv package,相应地,若在使用package缺少一些DLL文件,可以先尝试在msys2中找下,比如我这次在运行一个opencv sample时跳出缺少Libwebp-6.dll,通过使用dependency walker查看了下debug文件夹中的。
    		
    		exe文件,发现缺少不至Libwebp-6.dll文件,然后通过查找问题,终于在\url{https://sourceforge.net/p/msys2/discussion/general/thread/2b0cf1b4/}发现了similar problem,解决之道就是在msys2中找libwebp并安装。
    		\subsection{与codeblocks不太协调之处}
    		msys2安装的库文件在命名上都没有加上版本号，如"libopencv-core.dll",若为"libopencv-core310.dll"就更佳了，而codeblocks在创建opencv project时需要库的版本号，若版本号不一致会导致找不到库而无法创建project，
    		
    		解决办法：在库文件名上加上版本号。
    	\section{dependency walker}
    		下载：\url{http://www.dependencywalker.com/}
    		
    		使用方法参考:\url{http://blog.csdn.net/swort_177/article/details/5426848}，简而言之，处理对象DLL或exe。
    	\section{codeblocks}
    		\subsection{Global variable }
    		今天遇到一个关于Global varible的小问题，问题如下：我不小心将global varible中默认的variable改成另一个我自己添加的变量，结果当我运行最简单的"cout"输出都会弹框"无法定位程序输入点xxxxx于stdc++6.0.dll"，然后我查了下"C:\ Program Files (x86)\ CodeBlocks\ MinGW\ bin"，发现"stdc++6.0.dll"不是在嘛，后来在查看codeblocks的配置发现setting中global variable变掉了，再改过来就OK了。
    		
    		还有一点需要记录的是对于codeblock compiler的配置的层次性理解，global varible(大环境) > global compiler setting(小环境) > project compiler setting(个人爱好)
    		
    		\subsection{Global variable Editor}
    		可以按命名空间来设置相应packages的路径。
    		\subsection{linker setting}
    		链接器链接具体的库。
    		\subsection{how to set the -std=c++11 or -std=gnu++11 compiler options}
    		今天在将一些函数整理进头文件(.hpp)时出现了如下问题
\begin{lstlisting}[language=C++]
#if __cplusplus < 201103L
#error This file requires compiler and library support for the \
ISO C++ 2011 standard. This support is currently experimental, and must be \
enabled with the -std=c++11 or -std=gnu++11 compiler options.
#endif
\end{lstlisting}
			按如下途径设置Setting>compiler>general>C++0x上打勾或按如下途径设置右键项目>build options>compiler settings>compiler flags>c++0x打勾(一劳永逸)。
    	\section{spyder}
    		python集成开发环境。
    	\section{latex}
    	\subsection{Tikz学习}
    	%https://en.wikibooks.org/wiki/LaTeX/PGF/TikZ#Nodes
    	\url{https://en.wikibooks.org/wiki/LaTeX/PGF/TikZ#Nodes}
    	\subsection{遇到问题}
    		环境：texlive、texstudio。
    		
    		build：Xelatex;
    		
    		遇到问题：Fontconfig error: Cannot load default config file"C:\ texlive\ 2017\ texmf $-$ var\ fonts\ cache"。
    		
    		出现原因分析：缺少一个字体的配置文件，原因在于texlive2017安装不完全，当texlive文件个数安装完后会有一段时间来配置和生产cache文件在这段时间里电脑会比较卡，甚至安装窗口会出现”无响应“状态，注意此时切勿将安装窗口关闭，这会导致你安装的texlive不完整，上述问题就是因为缺少配置时本应生成的"fonts\ cache"。
    		
    		解决方法：1、若你对fonts的情况比较了解可以在此时文件下填补所需的文件。
    		
    				 2、重新安装texlive(较为切实可行的方法)。
    	\section{大华sdk学习记录}
    		\subsection{补丁安装}
    			大华安装包中自带的两个文件:Windows6.1-KB3033929-x64.msu和Windows6.1-KB2921916-x64.msu。
    			
    			其中，Windows6.1-KB3033929-x64.msu是更新程序，说明网站\url{https://www.microsoft.com/zh-CN/download/details.aspx?id=46148}。
    			
    			关于Windows6.1-KB2921916-x64.msu查到的资料是The "Untrusted publisher" dialog box appears when you install a driver in Windows 7 or Windows Server 2008 R2。
    			
    		\subsection{类的层次结构}
    		主要的处理对象有CSystem和ICamera。
    		
    		再细点的处理对象有CFrame。
    		
    	\section{大华sdk和opencv的结合使用问题}
    	如下放置头文件，
    	
\begin{lstlisting}[language=C++]
#include "GenICam/System.h"
#include "GenICam/Camera.h"
#include "GenICam/GigE/GigECamera.h"
#include "GenICam/GigE/GigEInterface.h"
#include "Infra/PrintLog.h"
#include "Memory/SharedPtr.h"
#include "Memory/Block.h"
#include <opencv2\opencv.hpp>
\end{lstlisting}

		会出现如下错误：
		
\begin{lstlisting}[language=C++]
error LNK2001: unresolved external symbol "public: void __cdecl cv::Mat::copyTo(class cv::debug_build_guard::_OutputArray const &)const "//错误
\end{lstlisting}	
		
		可能的原因分析：大华SDK的头文件比opencv的头文件先编译导致SOK先添加了相关的宏，而这些宏可能与opencv头文件中相关的宏冲突，这导致编译器忽视跳过了opencv头文件中的一些配置代码，从而丢失了链接。(这样认为的原因是如果多次link最后一次link会替换前几次link，这样不会就不会出现上述情况)
		
		解决方法：将opencv的头文件放在sdk的头文件之前。
		
		
	\chapter{论文阅读报告}
		\section{摩托车仪表图像自动检测方法研究张鼎}
			\subsection{难点}
				1、存在一些彩色的指示灯或图案，对阈值选取及差分图像处理会带来比较大的困难。
				
				2、检测过程中由于装卡装置的平移转动，其相对位置将不可避免地发生偏移，进而影响实际表盘刻度的真实位置。
				
				3、数字检测需要涉及液晶屏中形状的检测。
				
				4、分割二值图像中的数字，主要问题在于八段码连通域的分割问题。
			\subsection{软件构造}
				实现组成：仪表控制、摄像头采集图像和图像处理。
				
				配置：检测区域、检测项目的名称、检测项目的类型和检测项目的标准值。
				
				上位机：人机交互界面。	
			\subsection{硬件要求}
				通信：RS-485
				
				摄像机：摄像机分辨率选择基准：
				
				$$（垂直）水平方向分辨率=（垂直）水平方向最大尺寸 \setminus 检测精度$$
			\subsection{图像处理}
				图像预处理：
				
				1、灰度化 
				
				2、图像缩放（双线性插值）
					线性插值，保持斜率不变。
				3、Otsu阈值分割
				
				4、形态学变换
				
				四个运算：膨胀、腐蚀、开运算、闭运算
				
				感觉论文中的腐蚀公式（3-17）存在问题,公式应该为
				$$(B)_a = \{x|\exists a\in A,\forall b \in B:x=a-b\}$$
				$$A \Theta B=\{a|\exists a\in A, \forall\in B:a-b\in A\}=\{x|(B)_x \subset A\}$$
			
				5、轮廓查找及轮廓信息的应用
				
					对复杂几何图形使用凸包运算。
					
				6、数字识别及倾斜校正
				
					使用了穿线法识别数字，使用透视变换来将倾斜的数字校正。
					
					透视变换：
					
					理解的难点在于：透视变换的处理对象不是普通坐标(Ordinary Coordinate)而是齐次坐标(Homogeneous Coordinate)关于齐次坐标请参考几何章节。
					
					透视变换的原理参考：\url{http://www.cnblogs.com/liekkas0626/p/5262942.html}
					
					穿线法：
					
					\includegraphics[width=7cm, height=5cm]{cxf}
				
\end{document}
